package com.security.control.core.social.wx.connect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.social.oauth2.OAuth2Parameters;
import org.springframework.social.oauth2.OAuth2Template;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.Charset;

/**
 * @author imoot@gamil.com
 * @date 2019/1/7 0007 13:55
 * ----自定义OAuth2模板
 */
public class WxOAuth2Template extends OAuth2Template {

    private final String clientId;

    private final String clientSecret;

    private final String accessTokenUrl;

    private Logger log = LoggerFactory.getLogger(WxOAuth2Template.class);

    private static final String REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token";

    public WxOAuth2Template(String clientId, String clientSecret, String authorizeUrl, String accessTokenUrl) {
        super(clientId, clientSecret, authorizeUrl, accessTokenUrl);
        setUseParametersForClientAuthentication(true);
        this.clientId = clientId;
        this.clientSecret = clientSecret;
        this.accessTokenUrl = accessTokenUrl;
    }

    //创建rest请求模板
    @Override
    protected RestTemplate createRestTemplate() {
        RestTemplate restTemplate = super.createRestTemplate();
        restTemplate.getMessageConverters().add(new StringHttpMessageConverter(Charset.forName("UTF-8")));//加入"text/html"请求头对象，让模板能处理字符串信息
        return restTemplate;
    }

    @Override
    public AccessGrant exchangeForAccess(String authorizationCode, String redirectUri, MultiValueMap<String, String> additionalParameters) {
        StringBuffer resultUrl = new StringBuffer(accessTokenUrl);

        //把获取access_token的url拼接上如下key=value
        //?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
        resultUrl.append("?appid=").append(clientId)
                .append("&secret=").append(clientSecret)
                .append("&code=").append(authorizationCode)
                .append("&grant_type=authorization_code")
                .append("&redirect_uri=").append(redirectUri);
        return getForAccessGrant(resultUrl.toString());
    }


    @SuppressWarnings("unchecked")
    private AccessGrant getForAccessGrant(String accessTokenUrl) {
        String responseStr = getRestTemplate().getForObject(accessTokenUrl, String.class);
        log.info("获取accessToken的响应：" + responseStr);

        JSONObject resultObject = JSON.parseObject(responseStr);

        //判断错误code是否存在，如果有，则抛出获取失败异常
        if (resultObject.containsKey("errcode")) {
            String errcode = resultObject.getString("errcode");
            String errmsg = resultObject.getString("errmsg");
            log.error("获取access token失败, errcode:" + errcode + ", errmsg:" + errmsg);
            throw new RuntimeException("获取access token失败, errcode:" + errcode + ", errmsg:" + errmsg);
        }

        String accessToken = resultObject.getString("access_token");
        Long expiresIn = Long.valueOf(resultObject.getString("expires_in"));
        String refreshToken = resultObject.getString("refresh_token");
        String openId = resultObject.getString("openid");
        String scope = resultObject.getString("scope");

        WxAccessGrant wxAccessGrant = new WxAccessGrant(accessToken, scope, refreshToken, expiresIn);
        wxAccessGrant.setOpenId(openId);

        return wxAccessGrant;
    }

    public String buildAuthorizeUrl(OAuth2Parameters parameters) {
        return buildAuthenticateUrl(parameters);
    }

    /**
     * 构建获取授权码的请求（引导用户跳转到微信的地址）
     */
    public String buildAuthenticateUrl(OAuth2Parameters parameters) {
        StringBuffer url = new StringBuffer(super.buildAuthenticateUrl(parameters));
        url.append("&appid=").append(clientId)
                .append("&scope=snsapi_login");
        return url.toString();
    }
}
